// Go作者版权所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

package syntax

// ----------------------------------------------------------------------------
// 节点

type Node interface {
	// Pos（）返回与节点关联的位置，如下所示：
	// 1） 表示终端语法生成的节点的位置
	// （名称、基本单位等）是各自生产的位置
	// 在源代码中。
	// 2） 表示非终端产品的节点的位置
	// （IndexExpr、IfStmt等）是令牌的唯一位置
	// 与该生产相关；通常是最左边的
	// （“[”表示IndexExpr，“如果”表示IfStmt等）
	Pos() Pos
	aNode()
}

type node struct {
	// 由于尚未使用，暂时已注释掉
	// 文档*注释
	pos Pos
}

func (n *node) Pos() Pos { return n.pos }
func (*node) aNode()     {}

// ----------------------------------------------------------------------------
// 文件夹

// 包装PkgName；格点符号[0]，格点符号[1]。。。
type File struct {
	Pragma   Pragma
	PkgName  *Name
	DeclList []Decl
	EOF      Pos
	node
}

// ----------------------------------------------------------------------------
// 声明

type (
	Decl interface {
		Node
		aDecl()
	}

	// 路径
	// LocalPkgName路径
	ImportDecl struct {
		Group        *Group // nil表示不属于一个组
		Pragma       Pragma
		LocalPkgName *Name     // 包括",；nil表示不存在重命名
		Path         *BasicLit // Path.Bad | | Path.Kind==StringLit；零意味着没有路径
		decl
	}

	// 名单
	// 名称列表=值
	// 名称列表类型=值
	ConstDecl struct {
		Group    *Group // nil表示不属于一个组
		Pragma   Pragma
		NameList []*Name
		Type     Expr // nil表示没有类型
		Values   Expr // nil表示没有值
		decl
	}

	// 名称类型
	TypeDecl struct {
		Group      *Group // nil表示不属于一个组
		Pragma     Pragma
		Name       *Name
		TParamList []*Field // nil表示没有类型参数
		Alias      bool
		Type       Expr
		decl
	}

	// 姓名列表类型
	// 名称列表类型=值
	// 名称列表=值
	VarDecl struct {
		Group    *Group // nil表示不属于一个组
		Pragma   Pragma
		NameList []*Name
		Type     Expr // nil表示没有类型
		Values   Expr // nil表示没有值
		decl
	}

	// func名称类型{Body}
	// func名称类型
	// func接收方名称类型{Body}
	// func接收器名称类型
	FuncDecl struct {
		Pragma     Pragma
		Recv       *Field // nil表示正则函数
		Name       *Name
		TParamList []*Field // nil表示没有类型参数
		Type       *FuncType
		Body       *BlockStmt // 无表示无主体（远期声明）
		decl
	}
)

type decl struct{ node }

func (*decl) aDecl() {}

// 属于同一组的所有声明都指向同一组节点。
type Group struct {
	_ int // 不为空，因此保证使用不同的组实例
}

// ----------------------------------------------------------------------------
// 表达

func NewName(pos Pos, value string) *Name {
	n := new(Name)
	n.pos = pos
	n.Value = value
	return n
}

type (
	Expr interface {
		Node
		aExpr()
	}

	// 无法分析的表达式的占位符
	// 正确，我们无法提供更好的节点。
	BadExpr struct {
		expr
	}

	// 价值
	Name struct {
		Value string
		expr
	}

	// 价值
	BasicLit struct {
		Value string
		Kind  LitKind
		Bad   bool // true表示文字值有语法错误
		expr
	}

	// 类型{ElemList[0]，ElemList[1]，…}
	CompositeLit struct {
		Type     Expr // nil表示没有文本类型
		ElemList []Expr
		NKeys    int // 具有键的元素数
		Rbrace   Pos
		expr
	}

	// 关键词：价值
	KeyValueExpr struct {
		Key, Value Expr
		expr
	}

	// func类型{Body}
	FuncLit struct {
		Type *FuncType
		Body *BlockStmt
		expr
	}

	// （十）
	ParenExpr struct {
		X Expr
		expr
	}

	// X.塞尔
	SelectorExpr struct {
		X   Expr
		Sel *Name
		expr
	}

	// X[索引]
	// X[T1，T2，…]（带Ti=Index.（*ListExpr）.ElemList[i]）
	IndexExpr struct {
		X     Expr
		Index Expr
		expr
	}

	// X[索引[0]：索引[1]：索引[2]]
	SliceExpr struct {
		X     Expr
		Index [3]Expr
		// Full表示这是一个简单的还是完整的切片表达式。
		// 在有效的AST中，这相当于索引[2]！=无
		// TODO（mdempsky）：只需报告“3-index”即可
		// 缺少索引[2]时出现“字符串切片”错误。
		Full bool
		expr
	}

	// X.（类型）
	AssertExpr struct {
		X    Expr
		Type Expr
		expr
	}

	// X.（类型）
	// =Lhs（类型：）
	TypeSwitchGuard struct {
		Lhs *Name // 无表示无Lhs：=
		X   Expr  // X.（类型）
		expr
	}

	Operation struct {
		Op   Operator
		X, Y Expr // Y==nil表示一元表达式
		expr
	}

	// 乐趣（ArgList[0]，ArgList[1]，…）
	CallExpr struct {
		Fun     Expr
		ArgList []Expr // nil表示没有参数
		HasDots bool   // 最后一个参数后面是。。。
		expr
	}

	// ElemList[0]，ElemList[1]。。。
	ListExpr struct {
		ElemList []Expr
		expr
	}

	// [Len]Elem
	ArrayType struct {
		// toDo（GRI）考虑使用名称{“…”}代替NIL（允许附加注释）
		Len  Expr // nil表示Len是。。。
		Elem Expr
		expr
	}

	// []元素
	SliceType struct {
		Elem Expr
		expr
	}

	// …元素
	DotsType struct {
		Elem Expr
		expr
	}

	// 结构{FieldList[0]标记列表[0]；FieldList[1]标记列表[1]；…}
	StructType struct {
		FieldList []*Field
		TagList   []*BasicLit // i>=len（标记列表）| |标记列表[i]==nil表示字段i没有标记
		expr
	}

	// 名称类型
	// 类型
	Field struct {
		Name *Name // nil表示匿名字段/参数（结构/参数）或嵌入式接口（接口）
		Type Expr  // 列表中声明的字段名共享相同的类型（相同的指针）
		node
	}

	// 接口{MethodList[0]；MethodList[1]；…}
	InterfaceType struct {
		MethodList []*Field // 名为“type”的字段表示类型约束
		expr
	}

	FuncType struct {
		ParamList  []*Field
		ResultList []*Field
		expr
	}

	// 映射[键]值
	MapType struct {
		Key, Value Expr
		expr
	}

	// 陈艾琳
	// <-陈艾琳
	// 陈<-Elem
	ChanType struct {
		Dir  ChanDir // 0表示没有方向
		Elem Expr
		expr
	}
)

type expr struct{ node }

func (*expr) aExpr() {}

type ChanDir uint

const (
	_ ChanDir = iota
	SendOnly
	RecvOnly
)

// ----------------------------------------------------------------------------
// 声明

type (
	Stmt interface {
		Node
		aStmt()
	}

	SimpleStmt interface {
		Stmt
		aSimpleStmt()
	}

	EmptyStmt struct {
		simpleStmt
	}

	LabeledStmt struct {
		Label *Name
		Stmt  Stmt
		stmt
	}

	BlockStmt struct {
		List   []Stmt
		Rbrace Pos
		stmt
	}

	ExprStmt struct {
		X Expr
		simpleStmt
	}

	SendStmt struct {
		Chan, Value Expr // 陈<-价值
		simpleStmt
	}

	DeclStmt struct {
		DeclList []Decl
		stmt
	}

	AssignStmt struct {
		Op       Operator // 0表示没有操作
		Lhs, Rhs Expr     // Rhs==nil表示Lhs++（Op==Add）或Lhs--（Op==Sub）
		simpleStmt
	}

	BranchStmt struct {
		Tok   token // 中断、继续、中断或转到
		Label *Name
		// 目标是执行后控制流的延续
		// 分支机构；如果设置了checkBranchs，则由解析器计算。
		// 目标是一个用于gotos的*LabeledStmt和一个*SwitchStmt、*SelectStmt，
		// 或*ForStmt表示中断和继续，具体取决于
		// 树枝。未为故障设置目标。
		Target Stmt
		stmt
	}

	CallStmt struct {
		Tok  token // 去还是延期
		Call *CallExpr
		stmt
	}

	ReturnStmt struct {
		Results Expr // nil表示没有显式返回值
		stmt
	}

	IfStmt struct {
		Init SimpleStmt
		Cond Expr
		Then *BlockStmt
		Else Stmt // nil、*IfStmt或*BlockStmt
		stmt
	}

	ForStmt struct {
		Init SimpleStmt // 包括*条款
		Cond Expr
		Post SimpleStmt
		Body *BlockStmt
		stmt
	}

	SwitchStmt struct {
		Init   SimpleStmt
		Tag    Expr // 包括*类型开关防护装置
		Body   []*CaseClause
		Rbrace Pos
		stmt
	}

	SelectStmt struct {
		Body   []*CommClause
		Rbrace Pos
		stmt
	}
)

type (
	RangeClause struct {
		Lhs Expr // nil表示无Lhs=或Lhs：=
		Def bool // 指：=
		X   Expr // 范围X
		simpleStmt
	}

	CaseClause struct {
		Cases Expr // “无”是指违约条款
		Body  []Stmt
		Colon Pos
		node
	}

	CommClause struct {
		Comm  SimpleStmt // 发送或接收stmt；“无”是指违约条款
		Body  []Stmt
		Colon Pos
		node
	}
)

type stmt struct{ node }

func (stmt) aStmt() {}

type simpleStmt struct {
	stmt
}

func (simpleStmt) aSimpleStmt() {}

// ----------------------------------------------------------------------------
// 评论

// ToDo（GRI）考虑改名为评论、评论等。
// Kind=以上没有多大意义。
type CommentKind uint

const (
	Above CommentKind = iota
	Below
	Left
	Right
)

type Comment struct {
	Kind CommentKind
	Text string
	Next *Comment
}
